import json
import os
import shutil
import time

import ddddocr
import requests
from PIL import Image
from loguru import logger
from GTrace import GTrace

dir_path = os.path.dirname(os.path.abspath(__file__))
class Geetest(object):
    def __init__(self, gt, challenge):
        self.sess = requests.session()
        self.sess.headers = {
            'User-Agent': 'Mozilla/5.0 (Linux; Android 12; ANG-AN00 Build/HUAWEIANG-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 XWEB/1160055 MMWEBSDK/20231201 MMWEBID/9720 MicroMessenger/8.0.45.2521(0x28002D3D) WeChat/arm64 Weixin NetType/5G Language/zh_CN ABI/arm64',
            'Referer': 'https://cap.chinaunicom.cn/CAP-AUTH/auth-dx.html',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Accept': 'application/json, text/javascript, */*; q=0.01'
        }
        self.gt = gt
        self.challenge = challenge
        self.c = ''
        self.s = ''

    # 获取时间戳
    def get_t(self):
        return int(time.time() * 10000)

    # 获取js和css
    def get_script(self):
        url = 'https://apiv6.geetest.com/gettype.php?gt={}&callback=geetest_{}'.format(self.gt, self.get_t())
        response = self.sess.get(url).text
        data = self.getJson(response)['data']
        fullpage = data['fullpage']
        slide = data['slide']
        logger.info(f'1.2 gettype获取js版本，fullpage: {fullpage}  slide: {slide}')

    # 获取c和s参数
    def get_c_s(self):
        url = 'https://apiv6.geetest.com/get.php?gt={}&challenge={}&lang=zh-cn&pt=0&client_type=web&callback=geetest_{}'.format(
            self.gt, self.challenge, self.get_t())
        response = self.sess.get(url).text
        print(response)
        data = self.getJson(response)['data']
        c = data['c']
        s = data['s']
        logger.info(f'1.3 get.php获取c: {c}   s: {s}')  # c: [12, 58, 98, 36, 43, 95, 62, 15, 12]   s: 2a6e744e

    # 无感验证
    def get_type(self):
        url = 'https://api.geetest.com/ajax.php?gt={}&challenge={}&lang=zh-cn&pt=0&client_type=web&callback=geetest_{}'.format(
            self.gt, self.challenge, self.get_t())
        response = self.sess.get(url).text
        data = self.getJson(response)
        logger.info(f'2.1 ajax.php获取 {data}')  # {'status': 'success', 'data': {'result': 'slide'}}
        if data['status'] == 'success':
            if 'validate' in data['data']:
                return False, data['data']['validate']
        return True, ''

    # 获取缺口部分
    def get_x(self, newBg, newFullBg):
        slide = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
        with open(os.path.join(dir_path, newBg), 'rb') as f:
            target_bytes = f.read()
        with open(os.path.join(dir_path, newFullBg), 'rb') as f:
            background_bytes = f.read()

        res = slide.slide_comparison(target_bytes, background_bytes)
        return res['target'][0]

    # 恢复图片
    def spliceImg(self, imagePath, savePath):
        img = Image.open(imagePath)
        # 刚才的数组扣过来
        IMG_SHUFFLE_ORDER = [
            39, 38, 48, 49, 41, 40, 46, 47, 35, 34, 50, 51, 33, 32, 28, 29, 27, 26, 36, 37, 31, 30, 44, 45, 43, 42, 12,
            13, 23,
            22, 14, 15, 21, 20, 8, 9, 25, 24, 6, 7, 3, 2, 0, 1, 11, 10, 4, 5, 19, 18, 16, 17,
        ]
        # 图片会被切分为 10x80 的小图
        IMG_SHUFFLE_X_STEP = 10
        IMG_SHUFFLE_Y_STEP = 80

        # 最后图片的宽高
        IMG_WIDTH = 260
        IMG_HEIGHT = 160
        # 创建一个图对象片
        newImg = Image.new('RGB', (IMG_WIDTH, IMG_HEIGHT))
        # 按照顺序循环 52 次
        for i in range(len(IMG_SHUFFLE_ORDER)):
            x = IMG_SHUFFLE_ORDER[i] % 26 * 12 + 1
            y = IMG_SHUFFLE_Y_STEP if IMG_SHUFFLE_ORDER[i] > 25 else 0
            # 根据刚才 JS 的逻辑，把图片裁剪出一小块儿
            cut = img.crop((x, y, x + IMG_SHUFFLE_X_STEP, y + IMG_SHUFFLE_Y_STEP))
            # 根据刚才的逻辑，确定新图片的位置
            newX = i % 26 * 10
            newY = IMG_SHUFFLE_Y_STEP if i > 25 else 0
            # 把新图片拼接过去
            newImg.paste(cut, (newX, newY))
        newImg.save(savePath)

    # 保存图片
    def get_img_data(self, url, name):
        request = requests.get(url)
        with open(name, 'wb+') as f:
            f.write(request.content)
        f.close()

    # 获取jsonp数据
    def getJson(self, response):
        return json.loads(response[23:-1])

    # 获取背景图、滑块图
    def get_bg(self):
        url = 'https://api.geetest.com/get.php?is_next=true&type=slide3&gt={}&challenge={' \
              '}&lang=zh-cn&https=true&protocol=https%3A%2F%2F&offline=false&product=embed&api_server=api.geetest.com' \
              '&isPC=true&autoReset=true&width=100%25&callback=geetest_{}'.format(self.gt, self.challenge, self.get_t())
        response = self.sess.get(url).text
        print(response)
        data = self.getJson(response)
        self.challenge = data['challenge']
        self.c = data['c']
        self.s = data['s']
        logger.info(f'2.2 get.php获取 {data}')
        slice_big_img = 'https://static.geetest.com/' + data['bg']
        slice_full_img = 'https://static.geetest.com/' + data['fullbg']
        slice_small_img = 'https://static.geetest.com/' + data['slice']
        if os.path.isdir('pics') is False:
            os.mkdir('pics')
        times = 'pics/' + str(time.time_ns())
        if os.path.isdir(times) is False:
            os.mkdir(times)
        savePicName = {
            'bg': times + '/bg.png',
            'slice': times + '/slice.png',
            'fullbg': times + '/fullbg.png',
            'new-bg': times + '/new_bg.png',
            'new-fullbg': times + '/new_fullbg.png',
        }
        self.get_img_data(slice_big_img, savePicName['bg'])
        self.get_img_data(slice_small_img, savePicName['slice'])
        self.get_img_data(slice_full_img, savePicName['fullbg'])
        self.spliceImg(savePicName['bg'], savePicName['new-bg'])
        self.spliceImg(savePicName['fullbg'], savePicName['new-fullbg'])
        result_x = self.get_x(savePicName['new-bg'], savePicName['new-fullbg'])
        # 处理后，把图片删除掉
        shutil.rmtree(times)
        print('new x', result_x)
        gtrace = GTrace()
        # -10，图片不是从头部开始的
        distance, track = gtrace.get_mouse_pos_path(result_x - 10)
        import execjs
        with open('jiyan.js', 'r', encoding='utf-8') as f:
            js_code = f.read()
        result_x = track[-1][0]
        params = {
            'x': result_x,
            'c': self.c,
            's': self.s,
            'gt': self.gt,
            'challenge': self.challenge,
            'passtime': track[-1][2],
            'track': track
        }
        print(params)
        data = execjs.compile(js_code).call('init', params)
        logger.info(data)
        return self.submit(data)

    # 提交验证
    def submit(self, w):
        url = 'https://api.geetest.com/ajax.php?gt={}&challenge={}&lang=zh-cn&$_BCN=0&client_type=web&w={' \
              '}&callback=geetest_{}'.format(self.gt, self.challenge, w, self.get_t())
        response = self.sess.get(url).text
        data = self.getJson(response)
        logger.info(f'2.3 ajax.php提交 {data}')
        if data['success'] == 1 and data['message'] == 'success':
            return data['validate']
        else:
            return data


# if __name__ == '__main__':
#     gee = Geetest()
#     gee.getAuthNo()
#     # gee.get_gcl()
#     gee.get_script()
#     gee.get_c_s()
#     isNext, validate = gee.get_type()
#     if isNext == True:
#         gee.get_bg()
#     else:
#         print(validate)
